package com.huawei.springboot2023.business.user.service.impl;

import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.huawei.springboot2023.business.user.dto.LoginDto;
import com.huawei.springboot2023.business.user.dto.User;
import com.huawei.springboot2023.business.user.mapper.UserMapper;
import com.huawei.springboot2023.business.user.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huawei.springboot2023.core.dto.MyResult;
import com.huawei.springboot2023.core.util.MyJWTUtil;
import com.huawei.springboot2023.core.util.MyRedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author ZhouChengYang
 * @since 2023-04-05
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private MyRedisUtil redisUtil;

    @Value("${springDemo.errCount}")
    private Integer errCount; // 通过配置文件注入

    @Override
    public MyResult doLogin(LoginDto dto) {
        MyResult result = new MyResult();

        QueryWrapper<User> loginWrapper = new QueryWrapper<>();
        loginWrapper.eq("userName",dto.getUserName());
        // 数据库中存储的就是md5密文，判断密码是否相同要将用户填写的密码也通过md5加密比较密文是否相同
        loginWrapper.eq("pwd",DigestUtil.md5Hex(dto.getPwd()));

        User user = this.getOne(loginWrapper);

        if(user!=null){
            result.setMsg("登录成功！");

            //登录成功需要放置两个信息
            // user: 登录成功的当前用户实体信息
            // token: jwt令牌
            Map<String,Object> res = new HashMap<>();
            res.put("user",user);
            res.put("token", MyJWTUtil.getToken(dto.getUserName()));

            result.setData(res);

        }else{ // 用户名或密码错误

            // 根据用户名查询用户信息
            QueryWrapper<User> updateWrapper = new QueryWrapper<>();
            updateWrapper.eq("userName",dto.getUserName());

           User updateSelectDO = this.getOne(updateWrapper);

            if(updateSelectDO.getIsLock() == 1){// 用户已锁定

                result.setMsg("该用户已锁定，无法登录！");
                result.setCode("9999");
                return result;
            }
            // 修改用户信息对象
            User updateDO = new User();
            updateDO.setUserId(updateSelectDO.getUserId()); // 设置了更新条件，以用户id来进行更新

            // 对用户的输入错误次数进行记录
            int nowErrCount = updateSelectDO.getPwdErrorNum()+1;

            // 剩余几次尝试的机会 0
            int lessCount = this.errCount - nowErrCount;
            if(lessCount==0){ // 机会用完。账号锁定
                result.setMsg("用户名或密码错误，账号锁定请联系管理员！");
                result.setCode("9999");
                updateDO.setIsLock(1); // 设置账号锁定
            }else if(lessCount<=4){// 开启行为验证码
                // 保存当前用户需要开启行为验证码的记录
                redisUtil.set("xwyz#"+dto.getUserName(),1,60 * 10);
                result.setMsg("用户名或密码错误,还剩【"+lessCount+"】次尝试机会！");
                result.setCode("9999");
                updateDO.setPwdErrorNum(nowErrCount);
            }else{
                result.setMsg("用户名或密码错误,还剩【"+lessCount+"】次尝试机会！");
                result.setCode("9999");
                updateDO.setPwdErrorNum(nowErrCount);
            }

            // 更新当前用户的密码错误记录信息
            boolean b = this.updateById(updateDO);
            if(!b){
                result.setMsg("登录接口异常！");
                result.setCode("9999");
            }

        }

        return result;

    }
}
